from django.shortcuts import render_to_response
from django.template import RequestContext
from datetime import *
from django import forms

def get_at(obj,atr):
	value = ""
	try:
		value = getattr(obj, atr)()
	except:
		try:
			value = getattr(obj, atr)
		except:
			value = atr.replace('"','')
	if isinstance(value,date):
		value = value.strftime("%d/%m/%Y")
	if isinstance(value,float):
		value = long(value * 100)/100.0
	return value
			
			
class F(object):
	def __init__(self, name, verbose='', solo_con_items =False, title=True, items =[], filter={}, total=False, total_child=None):
		self.name = name
		self.verbose = verbose
		self.title = title
		self.items = items	
		self.total = total
		self.column = 0
		self.positions = []
		self.totals = {}
		self.total_child = total_child
		self.filter= filter
		self.solo_con_items = solo_con_items
		for i in self.items:
			i.parent = self
	
	def __str__(self):
		return self.get_title()
	
	def items_count(self):
		self.set_column(0)
		pos = 0
		for r in self.positions:
			if r:
				if r.column > pos: pos = r.column
		return pos
		

	def max_count(self):
		cant= 0
		for i in self.items:
			if i.items:
				cant += i.max_count()
			else:
				cant += 1
		return cant

	def find_item(self, name):
		for i in self.items:
			if i.get_title()== name:
				return i
			if i.items:
				return i.find_item(name)
		return None

	def set_column(self, column, root=None):
		# self: este nivel
		# root: el primer nivel
		if not root: 
			root=self
			root.positions=[None]*(self.max_count()+1)
		for i in self.items:
			if i.items:
				i.set_column(column, root=root)
				column += i.max_count()
			else:
				j = root.find_item(i.get_title())
				
				if j.column: #la columna ya existia
					i.column = j.column
				else: # columna nueva
					for c in range(1, column):
						if not root.positions[c]:
							if not [j for j in self.items if j.column == c]:
								i.column = c
					if not i.column:
						i.column = column
						column += 1
				if i.title:
					root.positions[i.column]=i
			
				
	def get_title(self):
		if self.verbose:
			return self.verbose
		else:
			return self.name
		
	def has_total(self):
		# tiene un total en este nivel?
		for i in self.items:
			if i.total:
				return True
					
	def add_to_total(self, column, value):
		if value:
			value = float(value)
			if not column in self.totals:
				self.totals[column] = 0.0
			self.totals[column] += value
			try:
				self.parent.add_to_total (column, value)
			except:
				pass

	def set_total(self, column, value):
		if value:
			value = float(value)
			self.totals[column] = value
			try:
				self.parent.add_to_total (column, value)
			except:
				pass
	
	def clean_total(self):
		try:
			parent_attr = self.parent.parent.find_item(self.get_title())
		except:
			parent_attr = self
		return (parent_attr == self or not parent_attr.total_child) and (self.total or self.total_child)



def titles_to_table(table, size, select, nivel=0):
	if nivel==0:
		rec = [None] * size
		table.append (rec)
		rec.insert(0,"Title")
	else:
		rec = table[0]
	for attr in select.items:
		if attr.items:
			titles_to_table(table, size, attr, nivel+1)
		elif attr.title:
			rec[attr.column] =  attr.get_title()
	return table	



class Report():
	
	class ReportForm(forms.Form):
		pass
	
	def select(self):
		pass
	
	def query(self, form):
		pass
	
	def condition(self, form, nivel, obj):
		return True

	def view(self, request):
		select = self.select()
		query = []
		if request.method == 'GET':
			if len(request.GET) > 0:
				form = self.ReportForm(request.GET)
				if form.is_valid():	
					query = self.query(form)
			else:
				form = self.ReportForm()
								
			
		if request.method == 'POST':
			form = self.ReportForm(request.POST)
			if form.is_valid():	
				query = self.query(form)
				
		table = self.get_table(select, query, form)
		
		return render_to_response('report.html',locals(), context_instance=RequestContext(request))
		
	def printable(self, request):
		select = self.select()
		query = []
		if request.method == 'GET':
			form = self.ReportForm(request.GET)
			if form.is_valid():
				query = self.query(form)
			
		if request.method == 'POST':
			form = self.ReportForm(request.POST)
			if form.is_valid():
				query = self.query(form)
				
		table = self.get_table(select, query, form)
		
		return render_to_response('print.html',locals())

	def to_table(self, table, size, select, query, nivel=0, form=None):
		registros_agregados = 0
		if select.has_total():
			for attr in select.items:
				if attr.clean_total():
					select.totals[attr.get_title()] = 0.0
		#filter things
		for obj in query:
			if self.condition(form, nivel, obj):
				rec = [None] * size
				table.append (rec)
				hijos = 0
				for attr in select.items:
					if attr.items:
						attr_name = attr.name
						objs = get_at(obj,attr.name)
						if attr.filter:
							f = {}
							for k in attr.filter.keys():
								if form.cleaned_data[attr.filter[k]] <> "" and form.cleaned_data[attr.filter[k]] != None:
									f[k] = form.cleaned_data[attr.filter[k]]
							objs = objs.filter(**f)
						else:
							objs = objs.all()
						hijos = hijos + self.to_table(table, size, attr,objs,nivel+1,form)
					else:
						rec[attr.column-1] =  get_at(obj,attr.name)
						if attr.total_child:
							select.find_item(attr.total_child).set_total (attr.get_title(), rec[attr.column-1])
						elif attr.total:
							select.add_to_total (attr.get_title(), rec[attr.column-1])
				rec.insert(0,nivel)
				if hijos == 0 and select.solo_con_items:
					table.remove(rec)
				else:
					registros_agregados = registros_agregados + 1
					
	
		if select.has_total() and query:
			rec = [None] * size
			table.append (rec)
			for attr in select.items:
				if attr.total or attr.total_child:
					rec[attr.column-1]  = select.totals[attr.get_title()]
			rec.insert(0,"total-%s" % nivel)
		return registros_agregados


	def get_table(self, select, query, form=None):
		table = []
		select.set_column(1)
		titles_to_table (table, select.items_count(), select)
		self.to_table (table, select.items_count(), select, query, form=form)
		return table

	

